﻿using AdvancedTool.ExceptionHandler;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;

namespace AdvancedTool.Standard
{


    /// <summary>
    /// 经过封装的简化异步操作
    /// </summary>
    public class AsyncDoing : AsyncTasking
    {
        /// <summary>
        /// 异步操作结束
        /// </summary>
        public event Action<AsyncTasking> Resulting;
        /// <summary>
        /// 准备进行异步操作
        /// </summary>
        public event Action PreAction;
        /// <summary>
        /// 需要进行的异步操作
        /// </summary>
        public event Action BackgroundAction;
        protected override void PreInit()
        {
            base.PreInit();
            if (PreAction != null)
                PreAction();
        }
        protected override void BackgroundTask()
        {
            if (BackgroundAction != null)
                BackgroundAction();
        }
        protected override void PostResult()
        {
            base.PostResult();
            if (Resulting != null)
            {
                Resulting(this);
            }
        }
    }

    public abstract class AsyncTasking
    {
        protected Task NowTask;
        Dictionary<string, object> items = new Dictionary<string, object>();
        /// <summary>
        /// 获取全部的关键字
        /// </summary>
        /// <returns></returns>
        public string[] GetKeys()
        {
            string[] res = new string[items.Keys.Count];
            items.Keys.CopyTo(res, 0);
            return res;
        }
        /// <summary>
        /// 是否存在关键字
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Exist(string key)
        {
            return items.ContainsKey(key);
        }
        /// <summary>
        /// 通过关键字查找项
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object FindItem(string key)
        {
            if (items.ContainsKey(key))
                return items[key];
            else
                throw new AsyncTaskError("无指定项");
        }
        /// <summary>
        /// 存放数据对象
        /// </summary>
        /// <param name="key">关键字</param>
        /// <param name="item">数据对象</param>
        /// <returns>是否成功</returns>
        public bool PutItem(string key, object item)
        {
            if (!items.ContainsKey(key))
            {
                items.Add(key, item);
                return true;
            }
            else
                return false;
        }
        /// <summary>
        /// 存放数据对象
        /// </summary>
        /// <typeparam name="Titem">存放对象的类型</typeparam>
        /// <param name="key">关键字</param>
        /// <param name="item">数据对象</param>
        /// <returns>是否成功</returns>
        public bool PutItem<Titem>(string key, Titem item)
        {
            if (!items.ContainsKey(key))
            {
                items.Add(key, item);
                return true;
            }
            else
                return false;
        }
        /// <summary>
        /// 得到已存取的对象
        /// </summary>
        /// <typeparam name="Treturn">得到对象的类型</typeparam>
        /// <param name="key">关键字</param>
        /// <returns></returns>
        public Treturn FindItem<Treturn>(string key)
        {
            if (items.ContainsKey(key))
                return (Treturn)items[key];
            else
                throw new AsyncTaskError("无指定项");
        }

        protected virtual void PreInit()
        {
        }
        /// <summary>
        /// 进度变化动作
        /// </summary>
        /// <param name="progress"></param>
        /// <param name="task"></param>
        public delegate void ProgressUpdate(double progress, AsyncTasking task);
        /// <summary>
        /// 当进度变化时的时间
        /// </summary>
        public event ProgressUpdate OnProressUpdate;

        private double progess = 0;
        /// <summary>
        /// 异步进度，需要手动控制
        /// </summary>
        public double Progress
        {
            get => progess;
            set
            {
                progess = value;
                if (OnProressUpdate != null)
                    OnProressUpdate(value, this);
            }
        }
        protected virtual void PostResult()
        {

        }
        protected abstract void BackgroundTask();

        /// <summary>
        /// 以异步启动
        /// </summary>
        public async void InvokeAsync()
        {
            PreInit();
            Task task = new Task(delegate ()
            {
                BackgroundTask();
            }
            );
            NowTask = task;
            task.Start();
            await task;
            PostResult();
            task.Dispose();
        }

    }

    /// <summary>
    /// 文件查找工具
    /// </summary>
    public class FileFinder
    {
        /// <summary>
        /// 指定文件后缀，筛选用
        /// </summary>
        public string[] Extends
        {
            get;
            set;
        }
        /// <summary>
        /// 筛查的目标文件夹
        /// </summary>
        public string TargetDirectory
        {
            set;
            get;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="DirPath">文件夹路径</param>
        /// <param name="extends">指定处理特定的文件后缀</param>
        public FileFinder(string DirPath, params string[] extends)
        {
            Extends = extends;
            TargetDirectory = DirPath;
        }
        /// <summary>
        /// 文件被找到时的委托
        /// </summary>
        /// <param name="file">查找到的文件</param>
        public delegate void FileFindHandle(FileInfo file);
        /// <summary>
        /// 当文件被查找到时的事件
        /// </summary>
        public event FileFindHandle OnFileFound;
        /// <summary>
        /// 文件夹被找到时的委托
        /// </summary>
        /// <param name="directory">查找到的文件夹</param>
        public delegate void DirFindHandle(DirectoryInfo directory);
        /// <summary>
        /// 当文件夹被
        /// </summary>
        public event DirFindHandle OnDirFound;
        void Search(string path, bool ExtendsUse = true)
        {
            DirectoryInfo directory = new DirectoryInfo(path);
            foreach (DirectoryInfo info in directory.GetDirectories())
            {
                if (OnDirFound != null)
                {
                    OnDirFound(info);
                }
                Search(info.FullName, ExtendsUse);
            }
            foreach (FileInfo file in directory.GetFiles())
            {
                if (CheckExtend(file.Extension) || ExtendsUse == false)
                {
                    if (OnFileFound != null)
                    {
                        OnFileFound(file);
                    }
                }
            }
        }
        /// <summary>
        /// 启动查找
        /// </summary>
        /// <param name="IsUseExtends">是否限定查找特定后缀的文件，False即遍历全部文件</param>
        public void Search(bool IsUseExtends = true)
        {
            Search(TargetDirectory, IsUseExtends);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="directory">指定查找的文件夹</param>
        /// <param name="IsUseExtends">是否限定查找特定后缀的文件，False即遍历全部文件</param>
        public void Search(DirectoryInfo directory, bool IsUseExtends = true)
        {
            Search(directory.FullName, IsUseExtends);
        }

        bool CheckExtend(string fileextend)
        {
            if (Extends != null)
            {
                foreach (string e in Extends)
                {
                    if (fileextend.ToLower().Equals(e))
                    {
                        return true;
                    }
                }
                if (Extends.Length == 0)
                {
                    return true;
                }
                return false;
            }
            else
            {
                return true;
            }
        }
    }
    /// <summary>
    /// 外挂Dll管理器
    /// </summary>
    public class DllManager
    {
        /// <summary>
        /// 获取已读取的类拓展
        /// </summary>
        /// <param name="index">序号</param>
        /// <returns></returns>
        public ClassExtends this[int index] => ClassManager[index];

        /// <summary>
        /// 查找符合条件的类
        /// </summary>
        /// <param name="condition">查找条件</param>
        /// <returns></returns>
        public ClassExtends[] Search(FindDllCondition condition)
        {
            return ClassManager.FindAll(delegate (ClassExtends extends)
            {
                return condition.Invoke(extends);
            }
            ).ToArray();

        }
        /// <summary>
        /// 目前所含dll的总数
        /// </summary>
        public int Count => ClassManager.Count;

        List<ClassExtends> ClassManager = new List<ClassExtends>();
        /// <summary>
        /// 寻找特定Dll的委托
        /// </summary>
        /// <param name="extends">待判断的类拓展</param>
        /// <returns>True即读取，False即不读取</returns>
        public delegate bool FindDllCondition(ClassExtends extends);
        /// <summary>
        /// 启动，执行本类的其他操作前必须运行此函数
        /// </summary>
        public static DllManager InitializeInstances(string path)
        {
            DllManager manager = new DllManager();
            FileFinder finder = new FileFinder(path, ".dll");
            finder.OnFileFound += delegate (FileInfo file)
            {
                manager.ClassManager.Add(new ClassExtends(file.FullName));
            };
            finder.Search();
            finder = null;
            return manager;
        }
    }
    /// <summary>
    /// 函数启用工具
    /// </summary>
    public class MethodActivictor
    {
        /// <summary>
        /// 获取委托
        /// </summary>
        /// <typeparam name="T">委托的类型也是返回值</typeparam>
        /// <param name="owner">如果是静态函数则null，如果是实例函数则该函数的类实体</param>
        /// <param name="method">函数信息</param>
        /// <returns></returns>
        public static T GetDelegate<T>(object owner, MethodInfo method) where T : Delegate
        {
            return Delegate.CreateDelegate(typeof(T), owner, method) as T;
        }
        /// <summary>
        /// 查找指定名称的函数
        /// </summary>
        /// <param name="name">函数名</param>
        /// <param name="type">包含函数名的类</param>
        /// <returns></returns>
        public static MethodInfo FindMethod(string name, Type type)
        {
            MethodInfo method = type.GetMethod(name);
            if (method == null)
            {
                throw new Exception(string.Format("实体类：{0} 中无函数名为：{1} 的函数", type.FullName, name));
            }

            return method;
        }
        /// <summary>
        /// 获取委托
        /// </summary>
        /// <typeparam name="T">所要获取的委托类型</typeparam>
        /// <param name="owner">包含函数名的类实体</param>
        /// <param name="methodName">指定的函数名</param>
        /// <returns></returns>
        public static T GetDelegate<T>(object owner, string methodName) where T : Delegate
        {
            return GetDelegate<T>(owner, FindMethod(methodName, owner.GetType()));
        }
        /// <summary>
        /// 启动指定函数
        /// </summary>
        /// <param name="owner">包含函数的实体</param>
        /// <param name="method">函数信息</param>
        /// <param name="paramers">该函数要用到的参数</param>
        /// <returns></returns>
        public static object Invoke(object owner, MethodInfo method, params object[] paramers)
        {
            return method.Invoke(owner, paramers);
        }
        /// <summary>
        /// 启动指定函数
        /// </summary>
        /// <param name="owner">包含函数的实体</param>
        /// <param name="methodname">函数名</param>
        /// <param name="paramers">该函数要用到的参数</param>
        /// <returns></returns>
        public static object Invoke(object owner, string methodname, params object[] paramers)
        {
            MethodInfo method = FindMethod(methodname, owner.GetType());
            return method.Invoke(owner, paramers);
        }
    }
    /// <summary>
    /// 类拓展，读取Dll文件中的内容
    /// </summary>
    public class ClassExtends
    {
        private Assembly assembly;
        /// <summary>
        /// 获取到的所有类
        /// </summary>
        public Type[] ClassList => assembly.GetTypes();
        /// <summary>
        /// 获取当前Dll文件中的指定类
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Type this[string name] => assembly.GetType(name);
        /// <summary>
        /// 运行指定函数
        /// </summary>
        /// <param name="Owner">目标类实体</param>
        /// <param name="MethodName">函数名</param>
        /// <param name="MethodParameters">函数参数们</param>
        /// <returns>返回的是指定函数的返回值</returns>
        public object InvokeMethod(object Owner, string MethodName, params object[] MethodParameters)
        {

            object obj;
            try
            {
                Type objtype = Owner.GetType();
                obj = MethodActivictor.Invoke(Owner, MethodActivictor.FindMethod(MethodName, objtype), MethodParameters);
            }
            catch (Exception e)
            {
                return e.Message;
            }
            return obj;
        }
        /// <summary>
        /// 运行指定静态函数
        /// </summary>
        /// <param name="type">静态函数所在类</param>
        /// <param name="MethodName">函数名</param>
        /// <param name="MethodParameters">函数参数们</param>
        /// <returns>返回的是指定函数的返回值</returns>
        public object InvokeMethod(Type type, string MethodName, params object[] MethodParameters)
        {
            try
            {
                MethodInfo mi = MethodActivictor.FindMethod(MethodName, type);
                if (mi != null)
                {
                    return MethodActivictor.Invoke(null, mi, MethodParameters);
                }
                else
                {
                    return
                    null;
                }
            }
            catch (Exception e)
            {
                return e.Message;
            }
        }
        string path;
        /// <summary>
        /// 类库的文件源
        /// </summary>
        public string Source
        {
            set
            {
                path = Path.GetFullPath(value);
                try
                {
                    assembly = Assembly.LoadFile(path);
                }
                catch
                {
                    throw new Exception("读取的Dll错误,文件路径：" + path);
                }

            }
            get => path;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dllpath">类库文件路径</param>
        public ClassExtends(string dllpath)
        {
            Source = dllpath;
        }
        /// <summary>
        /// 
        /// </summary>
        public ClassExtends()
        {
            path = "";
        }
        /// <summary>
        /// 指定类是否存在
        /// </summary>
        /// <param name="className"></param>
        /// <returns></returns>
        public bool IsExist(string className)
        {
            if (ClassList.Length == 0)
            {
                throw new ClassExtendsException("该拓展Dll文件内无可用类");
            }
            foreach (Type type in ClassList)
            {
                if (type.Name.Equals(className))
                {
                    return true;
                }
            }
            return false;
        }

    }

}
